package com.gopay.bis.manager.bank.ebank;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.TransUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.icbc.ebank.pay.IcbcB2cMessage;
import com.gopay.common.domain.bank.icbc.ebank.pay.req.PayB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.pay.req.PayCustomB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.pay.req.PayMessageB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.pay.req.PayOrderB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.pay.req.PayOrderInfoB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.pay.req.PayOrdersB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.query.req.CmsQueryB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.query.req.EbQueryB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.query.req.InQueryB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.query.req.PubQueryB2CReq;
import com.gopay.common.domain.bank.icbc.ebank.query.res.CmsQueryB2CRes;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.remote.bank.BankManagerRemoteService;
import com.gopay.remote.bank.businesses.BankService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 工行支付网关B2C对象封装
 * 
 * IcbcB2CManager.java
 * @author WangHongFei
 */
public class IcbcB2cManager implements BankManagerRemoteService {
	
    private static final String XMLHEADER_B2C = "<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\" ?>\n";
    
    private static final String XMLHEADER_QUERY = "<?xml version=\"1.0\" encoding=\"GB2312\" ?>\n";
    
    @Resource(name = "icbcB2cBankServiceClient")
    private BankService icbcB2cBankServiceClient;
    
    @Resource(name = "icbcB2cBankServiceClientHna")
    private BankService icbcB2cBankServiceClientHna;
    
    @Resource(name = "icbcConfig")
    private Map<String, String> icbcConfig;
    /**
     * 工行B2C签名
     * 
     * @param BaseMessage
     * @return Object
     * @throws GopayException
     */
    public Object sign(BaseMessage message) throws GopayException {
    	IcbcB2cMessage messageB2C = (IcbcB2cMessage) message;
    	messageB2C.setGoodsId(" ");
    	messageB2C.setGoodsName("-");
    	messageB2C.setGoodsNum(" ");
    	messageB2C.setCarriageAmt(" ");
    	messageB2C.setMerCustomIp(" ");
    	messageB2C.setGoodsType("1");
    	messageB2C.setMerCustomID(" ");
    	messageB2C.setMerCustomPhone(" ");
    	messageB2C.setGoodsAddress("-");
    	messageB2C.setMerOrderRemark(" ");
    	messageB2C.setMerHint(" ");
    	messageB2C.setRemark1(" ");
    	messageB2C.setRemark2(" ");
    	messageB2C.setMerVAR(" ");
    	messageB2C.setBankUrl(messageB2C.getPayUrl());
    	messageB2C.setMerUrl(messageB2C.getPayRuturnUrl());
    	messageB2C.setInterfaceName(icbcConfig.get("ICBC.B2C.INTERFACENAME"));
    	messageB2C.setInterfaceVersion(icbcConfig.get("ICBC.B2C.INTERFACEVERSION"));
    	messageB2C.setInstallmentTimes(icbcConfig.get("ICBC.B2C.INSTALLMENTTIMES"));
    	messageB2C.setMeracct(icbcConfig.get("ICBC.B2C.MERACCT"));
    	messageB2C.setVerifyJoinFlag(icbcConfig.get("ICBC.B2C.VERIFYJOINFLAG"));
    	messageB2C.setLanguage("zh_CN");
    	messageB2C.setCurType(icbcConfig.get("ICBC.CURCODE.RMB"));
    	messageB2C.setMerid(messageB2C.getMerID());
        String creditType = icbcConfig.get("ICBC.B2C.CREDIT.TYPE");
        if (!message.isSupportCredit()) {
            creditType = "0";
        }
        messageB2C.setCreditType(creditType);
        messageB2C.setNotifyType(icbcConfig.get("ICBC.B2C.NOTIFYTYPE"));
        messageB2C.setResultType(icbcConfig.get("ICBC.B2C.RESULTTYPE"));
        messageB2C.setMerReference(icbcConfig.get("ICBC.B2C.MERREFERENCE"));
        messageB2C.setPlainMessage(buildPlain(messageB2C));
        BankLogUtils.printB2CManagerSignSendLog(messageB2C);
        if(messageB2C.isHna()){
        	messageB2C = (IcbcB2cMessage) icbcB2cBankServiceClientHna.sign(messageB2C);	
		}else{
			messageB2C = (IcbcB2cMessage) icbcB2cBankServiceClient.sign(messageB2C);
		}
        BankLogUtils.printB2CManagerSignReturnLog(messageB2C);
        return messageB2C;    	
    }

    /**
     * 工行B2C验签
     * 
     * @param BaseMessage
     * @return Object
     * @throws GopayException 
     */
    public Object verify(BaseMessage message) throws GopayException {
    	BankLogUtils.printB2CManagerVerifySendLog(message);
    	Map<String, Object> map;
    	 if(message.isHna()){
         		map = (Map<String, Object>) icbcB2cBankServiceClientHna.verify(message);	
 		}else{
               map = (Map<String, Object>) icbcB2cBankServiceClient.verify(message);
 		}
        BankLogUtils.printB2CManagerVerifyReturnLog(message, map);
        return map;
    }
    
    /**
     * 工行B2C查询
     * 
     * @param Object
     * @return Object
     * @throws GopayException 
     */
    public Object query(Object message) throws GopayException {
    	IcbcB2cMessage messageB2C = (IcbcB2cMessage) message;
        CmsQueryB2CReq cms = buildCms(messageB2C);
        Map<String, String> param = queryParam(cms);
        BankLogUtils.printB2CManagerQuerySendLog(messageB2C, param);
        CmsQueryB2CRes res;
        if(messageB2C.isHna()){
     		res = (CmsQueryB2CRes) icbcB2cBankServiceClientHna.query(param);	
		}else{
			res = (CmsQueryB2CRes) icbcB2cBankServiceClient.query(param);
		}
        res.setOutStlmCd(BankConstants.BANK_LOGO_ICBC); // 为了区分日志输出
        BankLogUtils.printB2CManagerQueryReturnLog(res);
        return res;
    }
    
    /**
     * 构建B2C签名明文串
     * 
     * @param IcbcB2cMessage
     * @return String
     */
    private String buildPlain(IcbcB2cMessage message) {
        PayB2CReq payB2C = new PayB2CReq();
        PayOrderInfoB2CReq orderInfo = new PayOrderInfoB2CReq();
        PayMessageB2CReq payMessage = new PayMessageB2CReq();
        PayOrdersB2CReq payOrders = new PayOrdersB2CReq();
        PayOrderB2CReq payOrder = new PayOrderB2CReq();
        PayCustomB2CReq payCustom = new PayCustomB2CReq();
        payB2C.setInterfaceName(message.getInterfaceName());
        payB2C.setInterfaceVersion(message.getInterfaceVersion());
        orderInfo.setOdate(message.getOrderDate());
        orderInfo.setCurType(message.getCurType());
        orderInfo.setMerId(message.getMerid());
        payOrder.setSubOrderId(message.getOrderId());
        payOrder.setSubAmount(message.getAmount().movePointRight(2).toString());
        payOrder.setInstallmentTimes(message.getInstallmentTimes());
        payOrder.setMerAcct(message.getMeracct());
        payOrder.setGoodsId(message.getGoodsId());
        payOrder.setGoodsName(message.getGoodsName());
        payOrder.setGoodsNum(message.getGoodsNum());
        payOrder.setCarriageAmt(message.getCarriageAmt());
        payCustom.setVerifyJoinFlag(message.getVerifyJoinFlag());
        payCustom.setLanguage(message.getLanguage());
        payMessage.setCreditType(message.getCreditType());
        payMessage.setNotifyType(message.getNotifyType());
        payMessage.setResultType(message.getResultType());
        payMessage.setMerReference(message.getMerReference());
        payMessage.setMerCustomIp(message.getMerCustomIp());
        payMessage.setGoodsType(message.getGoodsType());
        payMessage.setMerCustomId(message.getMerCustomID());
        payMessage.setMerCustomPhone(message.getMerCustomPhone());
        payMessage.setGoodsAddress(message.getGoodsAddress());
        payMessage.setMerOrderRemark(message.getMerOrderRemark());
        payMessage.setMerHint(message.getMerHint());
        payMessage.setRemark1(message.getRemark1());
        payMessage.setRemark2(message.getRemark2());
        payMessage.setMerUrl(message.getMerUrl());
        payMessage.setMerVar(message.getMerVAR());
        payOrders.setPayOrder(payOrder);
        orderInfo.setOrders(payOrders);
        payB2C.setOrderInfo(orderInfo);
        payB2C.setMessage(payMessage);
        payB2C.setCustom(payCustom);
        XStream xs = new XStream(new DomDriver());
        xs.autodetectAnnotations(true);
        String xml = xs.toXML(payB2C);
        xml = xml.replaceAll("\r", "");
        xml = xml.replaceAll("\n", "");
        xml = xml.replaceAll(" ", "");
        xml = xml.trim();    
        StringBuffer sb = new StringBuffer(XMLHEADER_B2C);
        sb.append(xml);
        return sb.toString();
    }

    /**
     * 构建B2C查询对象
     * 
     * @param IcbcB2cMessage
     * @return String
     */
    private CmsQueryB2CReq buildCms(IcbcB2cMessage message) {
        CmsQueryB2CReq cms = new CmsQueryB2CReq();
        EbQueryB2CReq eb = new EbQueryB2CReq();
        PubQueryB2CReq pub = new PubQueryB2CReq();
        InQueryB2CReq in = new InQueryB2CReq();
        // 交易代码
        pub.setTransCode(icbcConfig.get("ICBC.B2C.QUERY.TRANDCODE"));
        // 集团CIS
        pub.setCis(icbcConfig.get("ICBC.QUERY.CIS"));
        // 归属银行编号
        pub.setBankCode(icbcConfig.get("ICBC.QUERY.BANKCODE"));
        // 证书ID
        if("checker_1".equals(message.getLabel())){
            pub.setId(icbcConfig.get("ICBC.B2C.QUERY.ID.SEND1"));
        }else if("checker_2".equals(message.getLabel())){
            pub.setId(icbcConfig.get("ICBC.B2C.QUERY.ID.SEND2"));
        }else{
            pub.setId(message.getMerID2nd());
        }
        
        // 交易日期
        pub.setTranDate(DateUtils.getCurrDate("yyyyMMdd"));
        // 交易时间(微秒补零)
        pub.setTranTime(DateUtils.getCurrDate("HHmmssSS") + "000");
        // 指令包序列号
        pub.setFseqNo(TransUtils.getPackageID());
        // 商城类型
        in.setShopType(icbcConfig.get("ICBC.B2C.QUERY.SHOPTYPE"));
        // 商城代码
        in.setShopCode(icbcConfig.get("ICBC.B2C.QUERY.SHOPCODE"));
        if (BisBankBusinessProd._11.value.equals(message.getBankBusProd().value)) {
            // wap网关交易码
            in.setShopCode(icbcConfig.get("ICBC.WAP.B2C.QUERY.SHOPCODE"));
        }
        // 商城账号
        in.setShopAcct(icbcConfig.get("ICBC.B2C.QUERY.SHOPACCT"));
        // 待查订单号
        in.setQryOrderNum(message.getOrderId());
        // 待查交易序列号
        in.setQrySerialNo(" ");
        // 起始日期
        in.setBeginDate(DateUtils.getCurrDate("yyyyMMdd"));
        // 截止日期
        in.setEndDate(DateUtils.getCurrDate("yyyyMMdd"));
        // 开始时间
        in.setBeginTime("000000");
        // 终止时间
        in.setEndTime("235959");
        // 查询交易状态类型
        in.setResultType(" ");
        // 查询下页标识
        in.setNextTag(" ");
        // 请求备用字段1
        in.setReqRes1(" ");
        // 请求备用字段2
        in.setReqRes2(" ");
        
        eb.setPub(pub);
        eb.setIn(in);
        cms.setEb(eb);
        // 查询请求地址
        if("checker_1".equals(message.getLabel())){
            cms.setQueryUrl(icbcConfig.get("ICBC.B2C.QUERY.URL.SEND1"));
        }else if("checker_2".equals(message.getLabel())){
            cms.setQueryUrl(icbcConfig.get("ICBC.B2C.QUERY.URL.SEND2"));
        }else{
            cms.setQueryUrl(message.getQueryUrl());
        }
        
      
       
        return cms;
    }
    
    /**
     * 构建B2C查询参数
     * 
     * @param IcbcB2cMessage
     * @return String
     */
    private Map<String, String> queryParam(CmsQueryB2CReq req) {
        XStream xs = new XStream(new DomDriver());
        xs.autodetectAnnotations(true);
        // 生成请求报文
        String reqData = xs.toXML(req);
        StringBuffer sb = new StringBuffer(XMLHEADER_QUERY);
        sb.append(reqData);
        EbQueryB2CReq eb = req.getEb();
        PubQueryB2CReq pub = eb.getPub();
        Map<String, String> param = new HashMap<String, String>();
        param.put("userID", pub.getId());
        param.put("PackageID", pub.getFseqNo());
        param.put("SendTime", DateUtils.getCurrDate("yyyyMMddHHmmssSSS"));
        param.put("Version", icbcConfig.get("ICBC.QUERY.VERSION"));
        param.put("TransCode", pub.getTransCode());
        param.put("BankCode", pub.getBankCode());
        param.put("GroupCIS", pub.getCis());
        param.put("ID", pub.getId());
        param.put("PackageID", pub.getFseqNo());
        param.put("Cert", "");
        param.put("reqData", sb.toString());
        // 设置B2B交易
        param.put("tradeType", BankConstants.TRADE_B2C + "");
        param.put("queryUrl", req.getQueryUrl());
        return param;
    }

	@Override
	public Object dayend(BaseMessage base) throws GopayException, Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object refund(BaseMessage base) throws GopayException {
		// TODO Auto-generated method stub
		return null;
	}

}
